//
// Created by pxy on 2022/4/8.
//
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "GuiFrame.h"
#include <stb_image.h>
#include "Camera.h"
#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
#include <iostream>

namespace GuiFrame
{


Windows_Control* Windows_Control::controller= nullptr;

inline Windows_Control *Windows_Control::getController()
{
	if(controller== nullptr) controller=new Windows_Control();

	return controller;
}

void Windows_Control::Controller_free()
{
	free(controller);
}

GLFWwindow *Create_Glfw_Window()
{
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//指定版本
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//指定 核心模式下
	GLFWwindow *pWindow = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr);
	if (pWindow == nullptr)
	{
		std::cout << "窗口创建失败";
		return nullptr;
	}
	glfwMakeContextCurrent(pWindow);//创建opengl上下文
	//初始化 GLAD
	if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress))
	{
		std::cout << "初始化GLAD失败";
		return nullptr;
	}


	//告诉opengl 窗口大小
	glViewport(0, 0, WIN_WIDTH, WIN_HEIGHT);
	glfwSetFramebufferSizeCallback(pWindow,Windows_Control::getController()->framebuffer_size_callback);//设置窗口大小变化回调函数  重新设置 视口大小
	glfwSetCursorPosCallback(pWindow, Windows_Control::getController()->mouse_callback);
	glfwSetInputMode(pWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
	stbi_set_flip_vertically_on_load(true);
	glEnable(GL_DEPTH_TEST);
	return pWindow;
}









void Init_ImGui(GLFWwindow *pWindow)
{
	//创建imgui
	IMGUI_CHECKVERSION();
	ImGui::CreateContext();
	ImGuiIO &io = ImGui::GetIO();
	(void) io;
	ImGui::StyleColorsDark();
	ImGui_ImplGlfw_InitForOpenGL(pWindow, true);
	ImGui_ImplOpenGL3_Init("#version 330");
}

void Render_ImGui()
{
	ImGui_ImplOpenGL3_NewFrame();
	ImGui_ImplGlfw_NewFrame();
	ImGui::NewFrame();

	ImGui::Begin("FPS");
	ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate,
	            ImGui::GetIO().Framerate);
	ImGui::End();

	ImGui::Render();
	ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}












Windows_Control::Windows_Control()
:camera(glm::vec3(0.0f,0.0f,0.0f)),lastY(WIN_HEIGHT / 2.0f),
firstMouse(true), deltaTime(0.0f),lastFrame(0.0f),
mouse_catch(0),keyboard_catch(0)
{

}

void Windows_Control::processInput(GLFWwindow *window)
{
	if (glfwGetMouseButton(window, 1) == GLFW_PRESS)
	{
		glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
		mouse_catch = 1;
		keyboard_catch = 1;
	}

	if (glfwGetMouseButton(window, 1) == GLFW_RELEASE)
	{
		glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
		mouse_catch = 0;
		keyboard_catch = 0;
	}

	if (keyboard_catch == 1)
	{
		if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
			camera.ProcessKeyboard(FORWARD, deltaTime);
		if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
			camera.ProcessKeyboard(BACKWARD, deltaTime);
		if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
			camera.ProcessKeyboard(LEFT, deltaTime);
		if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
			camera.ProcessKeyboard(RIGHT, deltaTime);
	}
}

void Windows_Control::framebuffer_size_callback(GLFWwindow *window, int width, int height)
{
	glViewport(0, 0, width, height);
}

void Windows_Control::mouse_callback(GLFWwindow *window, double xposIn, double yposIn)
{
	if (getController()->mouse_catch == 1)
	{
		float xpos = static_cast<float>(xposIn);
		float ypos = static_cast<float>(yposIn);

		if (getController()->firstMouse)
		{
			getController()->lastX = xpos;
			getController()->lastY = ypos;
			getController()->firstMouse = false;
		}

		float xoffset = xpos - getController()->lastX;
		float yoffset = getController()->lastY - ypos; // reversed since y-coordinates go from bottom to top

		getController()->lastX = xpos;
		getController()->lastY = ypos;

		getController()->camera.ProcessMouseMovement(xoffset, yoffset);
	}
}


}